package com.yunzhu.yunzhubookingservice.interceptor;

import com.yunzhu.yunzhubookingservice.model.sys.AccessLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 使用拦截器统一对请求信息记录日志，解耦日志记录操作和业务代码
 * 利用拦截器的preHandle，afterCompletion两个方法在请求链路中执行的顺序，分别对请求进入Controller之前和Controller业务处理完成之后进行相关信息的日志记录
 * 在MyWebMvcConfigurer中把AccessLogInterceptor拦截器注册到Spring 中
 */
@Slf4j
public class AccessLogInterceptor implements HandlerInterceptor {
    //请求开始时间标识
    private static final String LOGGER_SEND_TIME = "SEND_TIME";
    //请求日志实体标识
    private static final String LOGGER_ACCESSLOG = "ACCESSLOG_ENTITY";

    /**
     * preHandle中构建进入SpringMVC的Controller之前开始记录日志实体，
     * 并把日志实体放入request中，传递到afterCompletion中取出，使用日志实体相关数据
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        AccessLog accessLog = new AccessLog();
        accessLog.setHttpMethod(request.getMethod());
        accessLog.setUrl(request.getRequestURI());
        //设置请求开始时间
        request.setAttribute(LOGGER_SEND_TIME,System.currentTimeMillis());
        //设置请求实体到request中，方便afterCompletion方法使用
        request.setAttribute(LOGGER_ACCESSLOG,accessLog);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //获取本次请求日志实体
        AccessLog accessLog = (AccessLog) request.getAttribute(LOGGER_ACCESSLOG);
        int status = response.getStatus();
        accessLog.setHttpStatus(status);
//        accessLog.setUsername("admin");//不同应用可能将访问者信息放在Session里或通过request传递，获取方法视情况
        accessLog.setUsername(request.getSession().getAttribute("username").toString());
        long currentTime = System.currentTimeMillis();
        long sendTime = Long.valueOf(request.getAttribute(LOGGER_SEND_TIME).toString());
        accessLog.setDuration(Integer.valueOf((currentTime-sendTime)+""));
        accessLog.setCreateTime(new Date());
        //将sysLog对象持久化保存
        log.info(accessLog.toString());
    }
}
